package org.example.atomictest;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author zhengdp
 * @Description 原子数组测试
 * @Date 2022/11/20 19:31
 * @Created by zhengdp
 */
public class AtomicArrayTest {
    public static void main(String[] args) {
        System.out.println("============ 不安全数组 =============");
        demo( () -> new int[10],
                ary -> ary.length,
                (ary,index) -> ary[index] ++,
                ary -> System.out.println(Arrays.toString(ary))
        );
        System.out.println("=========== 安全数组 ================");
        demo(
                () -> new AtomicIntegerArray(10),
                AtomicIntegerArray::length,
                AtomicIntegerArray::getAndIncrement,
                System.out::println
        );
    }

    /**
     *
     * @param arraySupplier 提供数组
     * @param lengthFun 获取数组长度的方法
     * @param putConsumer 自增方法，回传 array,index
     * @param pritConsumer 打印数组的方法
     * @param <T> 数组内元素类型
     */
    private static <T> void demo(Supplier<T> arraySupplier,
                                 Function<T,Integer> lengthFun,
                                 BiConsumer<T,Integer> putConsumer,
                                 Consumer<T> pritConsumer) {

        List<Thread> ts = new ArrayList<>();
        T array = arraySupplier.get();
        int length = lengthFun.apply(array);
        for(int i = 0; i < length;i++){
            ts.add(new Thread(() -> {
                // 每个线程 对数组进行10000次操作
                for( int j = 0; j< 10000 ; j++) {
                    putConsumer.accept(array,j%length);
                }
            }));
        }
        ts.forEach(Thread::start);
        ts.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        // 输出结果
        pritConsumer.accept(array);
    }
}
